fetch로 데이터 주고받기
✒️ 2025-05-28 10:00 내용 수정
- fetch 함수와 api를 사용하여 외부 서버에서 데이터를 요청하고, 그 데이터를 받아 사용할 수 있다.
- Fetch 참고.
API로 데이터 받기
- api.js : 외부 서버에 데이터를 요청하는 함수다.
- 모듈로 사용하여 다른 js 파일에서 import 하여 사용할 예정이다.
export async function getReviews() {
const res = await fetch('http://learn.codeit.kr/api/film-reviews');
const body = await res.json();
return body;
}
- App.js : api로 데이터를 요청해서 결과를 출력하는 함수다.
- useEffect 사용은 Hook과 State 참고.
import 'bootstrap/dist/css/bootstrap.min.css';
import '../App.css';
import { getReviews } from '../api';
import { useEffect, useState } from 'react';
function App() {
const [items, setItems] = useState();
// api로 데이터를 요청하여 받은 후 저장한다.
const dataLoad = async () => {
const {reviews} = await getReviews();
console.log('data loading complete!')
setItems(reviews);
}
// 렌더링 후 함수를 실행하도록 설정
useEffect(()=>{
dataLoad();
}, []); // clean-up 1회만 실행
const [flag, setFlag] = useState([true,true,true,true]);
const order = ['id', 'title', 'rating', 'createdAt'];
const orderName = ['아이디', '이름', '평점', '개봉일'];
const ratingDown = (n) => {
let result = [...items].filter((v)=>{return (v.rating < n)});
setItems(result);
}
const ratingUp = (n) => {
let result = [...items].filter((v)=>{return (v.rating >= n)});
setItems(result);
}
const dateUp = (n) => {
let dateCut = new Date(2020, n-1, 2).toISOString().substring(0, 10);
let result = [...items].filter((v)=>{
let date = new Date(v.createdAt).toISOString().substring(0, 10);
return date >= dateCut;
});
setItems(result);
}
const dateDown = (n) => {
let dateCut = new Date(2020, n-1, 2).toISOString().substring(0, 10);
let result = [...items].filter((v)=>{
let date = new Date(v.createdAt).toISOString().substring(0, 10);
return date < dateCut;
});
setItems(result);
}
const deleteItem = (id) => {
let result = [...items].filter((v)=>{return (v.id != id)});
setItems(result);
}
let orderList = (f, i) => {
let copy = [...flag];
if (i == 1) {
if (f) {
setItems([...items].sort((a, b) => {return a[order[i]].localeCompare(b[order[i]])}));
} else {
setItems([...items].sort((a, b) => {return b[order[i]].localeCompare(a[order[i]])}));
}
} else {
if (f) {
setItems([...items].sort((a, b) => (a[order[i]] - b[order[i]])));
} else {
setItems([...items].sort((a, b) => (b[order[i]] - a[order[i]])));
}
}
copy[i] = !copy[i];
setFlag(copy);
};
return (
<>
<section className='sec'>
<div className='container-lg'>
<h2 className='title'>Movie Reviews</h2>
<button className='btn btn-success' onClick={dataLoad}>출력하기</button>
{ // 렌더링을 진행하며 api로부터 데이터를 요청해서 저장한 후에만 출력되도록 설정했다.
// 정렬 버튼이나 필터링 버튼 등이 전부 items에 의존하기에 이 처리를 안 했을 때 오류로 인해 화면이 출력되지 않았다.
(items) ?
<div>
<div className='btn-wrap'>
{
order.map((el, i)=>{
return(
<button key={i} className='btn btn-primary' onClick={()=>{orderList(flag[i], i)}} >{
(flag[i]) ? orderName[i] + ' 오름차순' : orderName[i] + ' 내림차순'
} 정렬</button>
)
})
}
</div>
<div className='btn-wrap filter'>
<button className='btn btn-success' onClick={()=>{ratingDown(3)}}>평점 3점 미만만 보기</button>
<button className='btn btn-success' onClick={()=>{ratingUp(3)}}>평점 3점 이상만 보기</button>
<button className='btn btn-success' onClick={()=>{dateDown(11)}}>2020년 11월 이전만 보기</button>
<button className='btn btn-success' onClick={()=>{dateUp(11)}}>2020년 11월 이후만 보기</button>
</div>
<ReviewList items={items} deleteItem={deleteItem}></ReviewList>
</div>
: null
}
</div>
</section>
</>
);
}
// row
function ReviewList(props) {
let {items, deleteItem} = props; // props 객체 내에서 필요한 데이터 추출
return(
<>
<div className='row row-cols-1'>
{
items.map((el)=>{
return(
<ReviewListItem key={el.id} item={el} deleteItem={deleteItem}></ReviewListItem>
)
})
}
</div>
</>
)
}
// col
function ReviewListItem(props) { // props 객체 내에서 필요한 데이터 추출
let {id, title, imgUrl, rating, content, createdAt} = props.item;
let {deleteItem} = props;
let date = new Date(createdAt).toISOString().substring(0, 10);
return(
<>
{
<div className='col py-3'>
<div className='gt d-flex'>
<img src={imgUrl} ult={title}></img>
<div className='text-box'>
<ul>
<li><h3>{title}</h3></li>
<li>id : {id}</li>
<li>평점 : {rating}</li>
<li>생성 날짜 : {date}</li>
<li>줄거리 : {content}</li>
<li><button className='btn btn-dark' onClick={()=>{deleteItem(id)}}>삭제</button></li>
</ul>
</div>
</div>
</div>
}
</>
)
}
export default App;
- App.css
*{margin:0; padding:0; box-sizing: border-box;}
ul, ol, li{list-style: none;}
a{text-decoration: none;}
body{background-color: #e6e6e6;}
.sec{
width: 100%;
padding:50px 0;
}
.sec .btn-wrap .btn{margin:5px;}
.sec .gt{
padding: 30px;
background-color: #fff;
border-radius: 10px;
}
.sec .gt img{width: 20%;}
- api로 요청한 데이터가 출력되며, 여기서 필터링으로 일부 항목을 제거한 후 다시 출력하기 버튼을 누르면 데이터를 다시 요청받아 원본 데이터를 출력한다.